package com.song.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.song.entity.UserAccount;
import com.song.entity.UserInfo;
import com.song.exception.BusinessException;
import com.song.hfb.FormHelper;
import com.song.hfb.HfbConst;
import com.song.hfb.RequestHelper;
import com.song.mapper.UserAccountMapper;
import com.song.mapper.UserInfoMapper;
import com.song.service.TransFlowService;
import com.song.service.UserAccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.song.util.LendNoUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 用户账户 服务实现类
 * </p>
 *
 * @author Song
 * @since 2025-01-03
 */
@Service
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount> implements UserAccountService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private TransFlowService transFlowService;



    /**
     * 充值的方法
     * @param chargeAmt
     * @param userId
     * @return
     */
    @Override
    public String commitCharge(BigDecimal chargeAmt, Long userId) throws BusinessException {
        //根据用户id查询用户信息
        UserInfo userInfo = userInfoMapper.selectById(userId);

        //获取用户信息中的状态---（0：未绑定，1：绑定成功 -1：绑定失败）
        String bindCode = userInfo.getBindCode();

        //判断状态
        if ("0".equals(bindCode) || "-1".equals(bindCode)){//未绑定
            throw new BusinessException("该用户未绑定账户！请先绑定");
        }

        //准备参数
        /*
        agent_id	    int		        是	给商户分配的唯一标识
        agent_bill_no	string	    50	是	商户充值单号（要求唯一）
        bind_code	    string	    50	是	充值人绑定协议号。
        charge_amt	    decimal		    是	充值金额，即充值到汇付宝的金额。支持小数点后2位。
        fee_amt	        decimal		    是	商户收取用户的手续费。支持小数点后2位。可以传0。
        注意：从银行卡扣除金额= charge_amt+ fee_amt，用户汇付宝余额增加charge_amt，fee_amt转到商户账户。
        notify_url	    string	    255	是	通知商户充值成功的完整地址
        return_url	    string	    255	否	充值完成后同步返回商户的完整地址。
        timestamp	    long		    是	时间戳。从1970-01-01 00:00:00算起的毫秒数。
        sign	        string	    32	是	验签参数。

         */

        //将汇付宝官方文档中的参数放入集合，使用驼峰
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);//给商户分配的唯一标识
        paramMap.put("agentBillNo", LendNoUtils.getNo());//商户充值单号（要求唯一）

        paramMap.put("bindCode",bindCode);//充值人绑定协议号。
        paramMap.put("chargeAmt",chargeAmt);//充值金额

        paramMap.put("feeAmt",new BigDecimal("0"));//	商户收取用户的手续费
        paramMap.put("notifyUrl",HfbConst.RECHARGE_NOTIFY_URL);//通知商户充值成功的完整地址
        paramMap.put("returnUrl",HfbConst.RECHARGE_RETURN_URL); //充值完成后同步返回商户的完整地址。
        paramMap.put("timestamp", new Date().getTime());//时间戳
        paramMap.put("sign", RequestHelper.getSign(paramMap));//验签参数

        //将传入的参数构造成表单
        String form = FormHelper.buildForm(HfbConst.RECHARGE_URL, paramMap);//第一个参数是 用户绑定的url，第二个 接口需要的参数 !!


        return form;
    }

    /**
     * 充值成功之后的回调方法---需要满足幂等性
     *
     * @param objectMap
     */
    @Override
    public void notifyss(Map<String, Object> objectMap) {
        /*
            bind_code	string	50	是	充值人绑定协议号。
            charge_amt	decimal		是	充值金额
         */
        System.out.println("充值成功了!!!");
        String bindCode= (String) objectMap.get("bindCode");//返回的绑定码
        String chargeAmt= (String) objectMap.get("chargeAmt");//返回的充值金额

        baseMapper.updateUserAccount(bindCode,new BigDecimal(chargeAmt),new BigDecimal(0));

        //增加交易流水
        //增加交易流水
        //agent_bill_no	string	50	是	商户充值订单号
        String agentBillNo = (String) objectMap.get("agentBillNo");
        boolean result = transFlowService.isSaveTransFlow(agentBillNo);

        if(result){
            System.out.println("幂等性返回了.....");
            return;
        }

    }

    /**
     * 根据用户id查询该用户的账户信息
     * @param userId
     * @return
     */
    @Override
    public BigDecimal getAccountById(Long userId) {
        QueryWrapper<UserAccount> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId);

        UserAccount userAccount = baseMapper.selectOne(wrapper);
        //账户的钱
        BigDecimal amount = userAccount.getAmount();


        return amount;
    }
}
